﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;
using System.Threading;
namespace AcctrueWMS.Foundation.Util
{
    class CacheItem
    {
        public string Key
        {
            get;
            set;
        }
        public object Value
        {
            get;
            set;
        }
        public DateTime CacheTime
        {
            get;
            set;
        }
        public DateTime LastUseTime
        {
            get;
            set;
        }
    }
    /// <summary>
    /// 缓存组件，提供定时清理功能。
    /// </summary>
    public class CacheManager:IDisposable
    {
        private static CacheManager instance;
        private static object lockobj = new object();
        private static Dictionary<string, object> cacheDic = new Dictionary<string, object>();
        private static Thread clearThread = new Thread(new ThreadStart(Clear));//扫描线程
        private static TimeSpan expireTime = new TimeSpan(0,int.Parse("3000"),0);//过期时间
        private static TimeSpan interval =new TimeSpan(0,0,20);//清理间隔

        private CacheManager()
        {
            clearThread.Start();
        }
        public static CacheManager Instance
        {
            get 
            {
                lock (lockobj)
                {
                    if (instance == null)
                        instance = new CacheManager();
                    return instance;
                }
            }
        }
        //public void Add(string key,object obj)
        //{
        //    lock (lockobj)
        //    {
        //        cacheDic.Add(key, obj);
        //    }
        //}
        public object this[string key]
        {
            get
            {
                if (key == null)
                    throw new ArgumentNullException();
                if (key.Trim() == "")
                    throw new ArgumentException();

                lock (lockobj)
                {
                    CacheItem item = null;
                    if (cacheDic.ContainsKey(key))
                    {
                        item = cacheDic[key] as CacheItem;
                        item.LastUseTime = DateTime.Now;
                        if (HasExpired(item) && (DateTime.Now - item.LastUseTime) > interval)//如果已过期，还须计算上次使用时间和目前时间的间隔
                            item = null;
                    }
                    return item == null ? null : item.Value;
                }
            }
            set
            {
                lock (lockobj)
                {
                    if (!cacheDic.ContainsKey(key))
                        cacheDic.Add(key, null);
                    CacheItem item = new CacheItem();
                    item.Key = key;
                    item.Value = value;
                    item.CacheTime = DateTime.Now;
                    item.LastUseTime = DateTime.MinValue;
                    cacheDic[key] = item;
                }
            }
        }
        private static bool HasExpired(CacheItem item)
        {
            return (DateTime.Now - item.CacheTime) >=expireTime;
        }

        private static void Clear()
        {
            while (true)
            {
                //Thread.Sleep(int.Parse(Settings.CacheExpireTime));
                Thread.Sleep(interval);
                lock (lockobj)
                {
                    Collection<string> removeKeys = new Collection<string>();
                    foreach (string key in cacheDic.Keys)
                    {
                        CacheItem item = cacheDic[key] as CacheItem;
                        if (HasExpired(item) && (DateTime.Now - item.LastUseTime) > interval)//将到达过期时间，且上次使用时间和扫描时间已经超过一个间隔的清理
                            removeKeys.Add(key);
                    }
                    foreach (string key in removeKeys)
                        cacheDic.Remove(key);
                }
            }
        }

        #region IDisposable Members

        public void Dispose()
        {
            clearThread.Abort();
            cacheDic.Clear();

        }

        #endregion
    }
}
